package com.gx.utils;

import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.util.Map;

@Slf4j
public class ObjectUtil {

    private final static String GET = "get";
    private final static String SET = "set";

    public static <T> T get(Object o, String fieldName) {
        return getObject(o, fieldName, OpType.auto);
    }

    /**
     * 获取属性值
     *
     * @param o
     *            操作对象
     * @param fieldName
     *            属性名
     * @param opType
     *            操作属性方式
     * @return
     */
    @SuppressWarnings("unchecked")
    private final static <T> T getObject(Object o, String fieldName, OpType opType) {
        if (o == null || fieldName == null || fieldName.isEmpty() || opType == null) {
            throw new NullPointerException("参数: o,fieldName,opType 均不能为空");
        } else if (o instanceof Map) {
            return mapGet((Map<String, Object>) o, fieldName);
        }

        return operation(o, GET, fieldName, null, null, opType);
    }

    /**
     * map对象获取值
     *
     * @param map
     * @param fieldName
     *            属性
     * @return
     */
    private final static <T> T mapGet(Map<String, Object> map, String fieldName) {
        return (T) map.get(fieldName);
    }

    /**
     * @param o
     *            操作对象
     * @param methodName
     *            方法名
     * @param fieldName
     *            属性名
     * @param value
     *            值
     * @param opType
     *            操作属性方式
     * @return get方法返回实际值 set方法返回操作后对象
     */
    private final static <T> T operation(Object o, String methodType, String fieldName, Class<?> paramType, Object value, OpType opType) {
        T res = null;
        Class<?> type = o.getClass();
        if (GET.equals(methodType)) {
            if (isEmpty(type, fieldName)) {
                new Exception("未知属性，无法操作");
                return res;
            }
            try {
                res = (T) type.getDeclaredMethod(methodType + StringUtils.toUpperCaseFirstOne(fieldName)).invoke(o);
            } catch (Exception e) {
                log.info("读取属性发生异常",e);
            }
        }
        return res;
    }

    /**
     * 操作类型
     * @author GFuZan
     *
     */
    public static enum OpType {

        /**
         * 只操作属性
         */
        onlyField,
        /**
         * 只操作方法
         */
        onlyMethod,
        /**
         * 优先操作方法,操作方法失败时操作属性
         */
        auto;
    }


    public static Boolean isNotEmpty(Class clazz, String fieldName) {
        if (clazz == null || fieldName == null || fieldName.equals(""))
            return false;

        for (Field field : clazz.getDeclaredFields()) {
            if (field.getName().equals(fieldName)) {
                return true;
            }
        }
        return false;
    }

    public static Boolean isEmpty(Class clazz, String fieldName) {
        if (clazz == null || fieldName == null || fieldName.equals(""))
            return false;

        for (Field field : clazz.getDeclaredFields()) {
            if (field.getName().equals(fieldName)) {
                return false;
            }
        }
        return true;
    }
}
